/*
 *  XIO_Controller.h
 *  initiativeTracker
 *
 *  Created by Sam Jaffe on 5/10/12.
 *  Copyright 2012 WPI. All rights reserved.
 *
 */

#pragma once

#include <string>
#include <xercesc/dom/DOMDocument.hpp>
#include "xmlHandler.h"
#include "InitTracker.h"
#include "ClientServer.h"

template <class S, class R>
class XIOController;
template <class D>
class Server_XIO;
class Client_XIO;

class Message {
private:
    std::string pure;
    xercesc::DOMDocument* xmlDoc;
public:
    Message(std::string xml, XML_Handler* handler) {
        pure = xml;
        handler->parse(xml);
        xmlDoc = handler->getDocument();
    }
    ~Message() {}
    std::string str() const {return pure;}
    xercesc::DOMDocument* contents() const {return xmlDoc;}
    std::string id();
    
    static std::string requestHeader();
    static std::string responseHeader(const std::string req_ID);
    static std::string responseHeader(const std::string req_ID, 
                               const std::string reason);
    
    std::string echo();
};

template <class S, class R>
class XIOController 
: public XML_IO_Controller<std::shared_ptr<InitTracker>, S, R, void, Message*>{
public:
    XIOController(std::string schema) 
    : XML_IO_Controller<std::shared_ptr<InitTracker>, S, R, void, Message*>(schema) {}
    
    ~XIOController() {}
};

template <class D>
class Server_XIO : public XIOController<std::shared_ptr<Client_Thread<D>>, std::string> {
public:
    Server_XIO() {init();}
    Server_XIO(std::string schema) : XIOController<std::shared_ptr<Client_Thread<D>>, std::string>(schema) {init();}
    ~Server_XIO() {}
    void init();
    std::string process(Server<D>* serv, std::shared_ptr<Client_Thread<D>> client, std::string xmlMessage);
    std::string process(std::shared_ptr<InitTracker> target, std::shared_ptr<Client_Thread<D>> source, std::string xmlMessage);
    std::string recieve(std::shared_ptr<InitTracker> target, Message* xmlMessage);
    void send(std::shared_ptr<Client_Thread<D>> source, std::string xmlMessage);
};

class Client_XIO : public XIOController<std::shared_ptr<Server_Access>, void> {
public:
    Client_XIO(std::string schema) : XIOController(schema) {init();}
    ~Client_XIO() {}
    void init();
    void process(std::shared_ptr<InitTracker> target, std::shared_ptr<Server_Access> source,
                 std::string xmlMessage);
    void recieve(std::shared_ptr<InitTracker> target, Message* xmlMessage);
    void send(std::shared_ptr<Server_Access> source, std::string xmlMessage);
};

void process_changeTurn(std::shared_ptr<InitTracker> init, Message* xml);

void process_createUnit(std::shared_ptr<InitTracker> init, Message* xml);

void process_damageUnit(std::shared_ptr<InitTracker> init, Message* xml);

void process_delayTurn(std::shared_ptr<InitTracker> init, Message* xml);

void process_killUnit(std::shared_ptr<InitTracker> init, Message* xml);

void process_killAllUnits(std::shared_ptr<InitTracker> init, Message* xml);

void process_nullInitiative(std::shared_ptr<InitTracker> init, Message* xml);

void process_rollInitiative(std::shared_ptr<InitTracker> init, Message* xml);

void process_healingSurge(std::shared_ptr<InitTracker> init, Message* xml);

void process_download(std::shared_ptr<InitTracker> init, Message* xml);

std::string process_upload(std::shared_ptr<InitTracker> init, std::shared_ptr<Client> xml);

void rotate(xercesc::DOMNode*& node);
